// @ts-nocheck
interface SelectOptions {
  context?: any
  needAll?: boolean
  node?: boolean
}
// #ifdef MP
function selectMPComponent(key: string, name: string, context: any, needAll: boolean) {
  const { proxy, $vm } = context
  context = $vm || proxy
  if (!['ref', 'component'].includes(key)) {
    const queue = [context]
    let result = null
    const selector = (key == 'id' ? '#' : '.') + name
    while (queue.length > 0) {
      const child = queue.shift()
      const flag = child?.selectComponent(selector)
      if (flag) {
        if (!needAll) {
          return (result = flag.$vm)
        }
        return (result = child.selectAllComponents(selector).map((item) => item.$vm))
      } else {
        child.$children && queue.push(...child.$children)
      }
    }
    return result
  } else {
    const { $templateRefs } = context.$
    const nameMap = {}
    for (var i = 0; i < $templateRefs.length; i++) {
      const item = $templateRefs[i]
      nameMap[item.i] = item.r
    }
    let result = []
    if (context.$children.length) {
      const queue = [...context.$children]
      while (queue.length > 0) {
        const child = queue.shift()
        if (key == 'component' && (child.type?.name === name || child.$?.type?.name === name)) {
          result.push(child)
        } else if (child.$refs && child.$refs[name]) {
          result = child.$refs[name]
        } else if (nameMap[child.id] === name) {
          result.push(child)
        } else {
          child.$children && queue.push(...child.$children)
        }
        if (result.length && !needAll) {
          return
        }
      }
    }
    return needAll ? result : result[0]
  }
}
// #endif
// #ifdef H5
function selectH5Component(key: string, name: string, context: any, needAll: boolean) {
  const { _, component } = context
  const child = { component: _ || component || context, children: null, subTree: null, props: null }
  let result = []
  let queue = [child]
  while (queue.length > 0) {
    const child = queue.shift()
    const { component, children, props, subTree } = child
    if (key === 'component' && component?.type?.name == name) {
      result.push(component)
    } else if (key === 'ref' && component && (props?.ref == name || component[key][name])) {
      if (props?.ref == name) {
        //exposed
        result.push(component)
      } else if (component[key][name]) {
        result.push(component[key][name])
      }
    } else if (
      key !== 'ref' &&
      component?.exposed &&
      new RegExp(`\\b${name}\\b`).test(component.attrs[key])
    ) {
      // exposed
      result.push(component)
    } else if (children && Array.isArray(children)) {
      queue.push(...children)
    } else if (!component && subTree) {
      queue.push(subTree)
    } else if (component?.subTree) {
      queue.push(component.subTree)
    }
    if (result.length && !needAll) {
      break
    }
  }
  return needAll ? result : result[0]
}
// #endif
// #ifdef APP
function selectAPPComponent(
  key: string,
  name: string,
  context: any,
  needAll: boolean,
  node: boolean,
) {
  let result = []
  // const {_, component} = context
  // const child = {component: _ || component || context, children: null, props: null, subTree: null}
  const queue = [context]
  while (queue.length > 0) {
    const child = queue.shift()
    const { component, children, props, subTree } = child
    const isComp = component && props && component.exposed && !node
    if (key == 'component' && child.type && child.type.name === name) {
      result.push(component)
    } else if (props?.[key] === name && node) {
      result.push(child)
    } else if (key === 'ref' && isComp && (props.ref === name || props.ref_key === name)) {
      // exposed
      result.push(component)
    } else if (key !== 'ref' && isComp && new RegExp(`\\b${name}\\b`).test(props[key])) {
      // exposed
      result.push(component)
    }
    // else if(component && component.subTree && Array.isArray(component.subTree.children)){
    // 	queue.push(...component.subTree.children)
    // }
    else if (subTree) {
      queue.push(subTree)
    } else if (component && component.subTree) {
      queue.push(component.subTree)
    } else if (children && Array.isArray(children)) {
      queue.push(...children)
    }
    if (result.length && !needAll) {
      break
    }
  }
  return needAll ? result : result[0]
}
// #endif
export function selectAllComponent(selector: string, options: SelectOptions = {}) {
  // . class
  // # id
  // $ ref
  // @ component name
  const reg = /^(\.|#|@|\$)([a-zA-Z_0-9\-]+)$/
  if (!reg.test(selector)) return null
  let { context, needAll = true, node } = options
  const [, prefix, name] = selector.match(reg)
  const symbolMappings = { '.': 'class', '#': 'id', $: 'ref', '@': 'component' }

  const key = symbolMappings[prefix] //prefix === '.' ? 'class' : prefix === '#' ? 'id' : 'ref';
  // #ifdef MP
  return selectMPComponent(key, name, context, needAll)
  // #endif
  // #ifdef H5
  return selectH5Component(key, name, context, needAll)
  // #endif
  // #ifdef APP
  return selectAPPComponent(key, name, context, needAll, node)
  // #endif
}
